package com.gzm.health;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gzm.check.entity.BaseHealthCheckup;
import com.gzm.check.service.IBaseHealthCheckupService;
import com.gzm.follow.entity.BaseDiabetesVisit;
import com.gzm.follow.entity.BaseHighBloodVisit;
import com.gzm.follow.entity.BaseSpiritVisit;
import com.gzm.follow.entity.BaseTuberculosisVisit;
import com.gzm.follow.service.IBaseDiabetesVisitService;
import com.gzm.follow.service.IBaseHighBloodVisitService;
import com.gzm.follow.service.IBaseSpiritVisitService;
import com.gzm.follow.service.IBaseTuberculosisVisitService;
import com.gzm.health.entity.BaseHealthRecord;
import com.gzm.health.entity.Record;
import com.gzm.health.entity.RecordTwo;
import com.gzm.health.service.IBaseHealthRecordService;
import com.gzm.health.service.IRecordService;
import com.gzm.health.service.IRecordTwoService;
import com.gzm.health.util.BasicConstant;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicLong;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HealthRecode {

    @Autowired
    private IBaseHealthRecordService iBaseHealthRecordService;
    @Autowired
    private IRecordService iRecordService;
    @Autowired
    private IRecordTwoService iRecordTwoService;
    @Autowired
    private IBaseHealthCheckupService iBaseHealthCheckupService;
    @Autowired
    private IBaseDiabetesVisitService iBaseDiabetesVisitService;
    @Autowired
    private IBaseHighBloodVisitService iBaseHighBloodVisitService;
    @Autowired
    private IBaseSpiritVisitService iBaseSpiritVisitService;
    @Autowired
    private IBaseTuberculosisVisitService iBaseTuberculosisVisitService;


    // 分页开始,第一页
    private static final AtomicLong ATOMICLONG = new AtomicLong(1);

    // 每页条数,默认一次处理一万条数据
    private static final int IMIT = 10000;

    // 最大线程数
    private static final int MAXTHREAD = 10;

    // 线程池
    private static final ExecutorService pool = Executors.newFixedThreadPool(MAXTHREAD);

    // 信号量
    private static final Semaphore SEMAPHORE = new Semaphore(MAXTHREAD);

    @Test
    public void getTest() {
        QueryWrapper<BaseHealthRecord> queryWrapper = new QueryWrapper<>();
        //queryWrapper.eq("status", 0);
        queryWrapper.orderByAsc("health_Id");

        LocalDateTime start = LocalDateTime.now(); // 开始时间

        while (true) {
            long andIncrement = ATOMICLONG.getAndIncrement();
            Page<BaseHealthRecord> page = iBaseHealthRecordService.page(new Page<BaseHealthRecord>(andIncrement, IMIT), queryWrapper);

            List<BaseHealthRecord> records = page.getRecords();
            if (IterUtil.isEmpty(records) || IMIT > records.size()) {
                // 最后一次的数据了
                setRecode(records, 0, records.size());
                break;// 处理完直接跳出
            }
            for (int i = 0; i < MAXTHREAD; i++) {
                int pages = i;
                pool.execute(() -> { // 多线程执行
                    setRecode(records, pages * (IMIT / MAXTHREAD), (pages + 1) * (IMIT / MAXTHREAD));
                });
            }
            try {
                Thread.sleep(1000); // 主线程睡眠一秒防止下面抢到凭证
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                SEMAPHORE.acquire(MAXTHREAD); // 一次获取最大凭证数保证所有线程都执行完毕
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SEMAPHORE.release(MAXTHREAD);// 重置型号量
            String fromat = StrUtil.format("====> 执行完了第{} 次", andIncrement);
            System.out.println(fromat);

        }

        LocalDateTime end = LocalDateTime.now();// 结束时间
        Duration between = LocalDateTimeUtil.between(start, end);


        String sta = LocalDateTimeUtil.format(start, DatePattern.NORM_DATETIME_PATTERN);
        String en = LocalDateTimeUtil.format(end, DatePattern.NORM_DATETIME_PATTERN);

        String format = StrUtil.format("开始时间 : {} ,结束时间 : {} ,执行时间 :{}分钟", sta, en, between.toMinutes());
        System.out.println(format);
        pool.shutdown();// 销毁线程池

    }

    // 将处理过的数据保存到新库中
    public void setRecode(List<BaseHealthRecord> list, int begin, int end) {
        try {
            SEMAPHORE.acquire();// 获取凭证
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        List<Record> lists = new ArrayList<>(1000);
        List<RecordTwo> list2 = new ArrayList<>(1000);
        for (int i = begin; i < end; i++) {
            BaseHealthRecord record = list.get(i);
            baseHealthToRecode(list.get(i), lists, list2);
        }
        boolean b = iRecordService.saveBatch(lists);
        boolean b1 = iRecordTwoService.saveBatch(list2);
        SEMAPHORE.release();// 线程执行完释放凭证
    }

    // 将老库中的数据解析为新库对象放到集合中
    public void baseHealthToRecode(BaseHealthRecord record, List<Record> lists, List<RecordTwo> list2) {
        Record re = new Record();
        re.setHealthId(record.getHealthId());
        re.setFamilyId(record.getFamilyId());
        re.setIdNumber(record.getIdNumber());
        re.setName(record.getName());
        re.setGender(record.getGender());
        re.setBirthDate(record.getBirthDate());
        re.setNation(record.getNation());
        re.setDomicileType(record.getDomicileType());
        re.setContactAddress(record.getContactAddress());
        re.setP1(record.getP1());
        re.setP2(record.getP2());
        re.setP3(record.getP3());
        re.setP4(record.getP4());
        re.setP5(record.getP5());
        re.setPhone(record.getPhone());
        re.setCreateuserid(record.getCreateuserid());
        re.setPinyin(record.getPinyin());
        re.setStatus(record.getStatus());
        re.setPoverty(StrUtil.isBlank(record.getPoverty()) ? null : Convert.toInt(record.getPoverty()));
        re.setPovertyType(record.getPovertyType());
        re.setDisease(record.getDisease());
        re.setNewborn(record.getNewborn());
        re.setCreatTime(record.getCreatTime());
        re.setCreatTime(record.getCreatTime());
        re.setWomanDisease(record.getWomanDisease());
        re.setOldDisease(record.getOldDisease());
        re.setOldTime(record.getOldTime());
        re.setHighbloodDisease(record.getHighbloodDisease());
        re.setHighbloodTime(record.getHighbloodTime());

        QueryWrapper<BaseHighBloodVisit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("HEALTH_ID", record.getHealthId());
        queryWrapper.orderByDesc("VISIT_TIME").last("limit 1");
        BaseHighBloodVisit highBloodVisit = iBaseHighBloodVisitService.getOne(queryWrapper);
        if (highBloodVisit != null) {
            re.setLastHighbloodTime(highBloodVisit.getVisitTime());
            re.setNextHighbloodTime(highBloodVisit.getNextVisitTime());
            re.setHighbloodCount(iBaseHighBloodVisitService.count(new QueryWrapper<BaseHighBloodVisit>().eq("HEALTH_ID", record.getHealthId())));
        }

        re.setDiabetesDisease(record.getDiabetesDisease());
        QueryWrapper<BaseDiabetesVisit> query2 = new QueryWrapper<>();
        query2.eq("HEALTH_ID", record.getHealthId());
        query2.orderByDesc("VISIT_TIME").last("limit 1");
        BaseDiabetesVisit dia = iBaseDiabetesVisitService.getOne(query2);
        if (dia != null) {
            re.setLastDiabetesTime(dia.getVisitTime());
            re.setNextDiabetesTime(dia.getNextVisitTime());
            re.setDiabetesCount(iBaseDiabetesVisitService.count(new QueryWrapper<BaseDiabetesVisit>().eq("HEALTH_ID", record.getHealthId())));
        }
        re.setTuberculDisease(record.getTuberculDisease());
        QueryWrapper<BaseTuberculosisVisit> query3 = new QueryWrapper<>();
        query3.eq("HEALTH_ID", record.getHealthId());
        query3.orderByDesc("VISIT_TIME").last("limit 1");
        BaseTuberculosisVisit tub = iBaseTuberculosisVisitService.getOne(query3);
        if (tub != null) {
            re.setLastTuberculTime(tub.getVisitTime());
            re.setNextTuberculTime(tub.getNextVisitTime());
            re.setTuberculCount(iBaseTuberculosisVisitService.count(new QueryWrapper<BaseTuberculosisVisit>().eq("HEALTH_ID", record.getHealthId())));
        }
        re.setSpiritDisease(record.getSpiritDisease());
        QueryWrapper<BaseSpiritVisit> query4 = new QueryWrapper<>();
        query4.eq("HEALTH_ID", record.getHealthId());
        query4.orderByDesc("VISIT_TIME").last("limit 1");
        BaseSpiritVisit spirit = iBaseSpiritVisitService.getOne(query4);
        if (spirit != null) {
            re.setLastSpiritTime(spirit.getVisitTime());
            re.setNextSpiritTime(spirit.getNextVisitTime());
            re.setSpiritCount(iBaseSpiritVisitService.count(new QueryWrapper<BaseSpiritVisit>().eq("HEALTH_ID", record.getHealthId())));
        }

        re.setCheckeCount(iBaseHealthCheckupService.count(new QueryWrapper<BaseHealthCheckup>().eq("HEALTH_ID", record.getHealthId())));
        lists.add(re);
        RecordTwo res = new RecordTwo();
        res.setHealthId(record.getHealthId());
        res.setNationality(record.getNationality());
        res.setWorkUnit(record.getWorkUnit());
        Map<String, String> father = getDisease(record.getFather(), 13, true);
        res.setFather(father.get("code"));
        res.setFatherOther(father.get("other"));
        Map<String, String> mother = getDisease(record.getMother(), 13, true);
        res.setMother(mother.get("code"));
        res.setMotherOther(mother.get("other"));
        Map<String, String> sister = getDisease(record.getFather(), 13, true);
        res.setSister(sister.get("code"));
        res.setSisterOther(sister.get("other"));
        Map<String, String> son = getDisease(record.getMother(), 13, true);
        res.setSon(son.get("code"));
        res.setSonOther(son.get("other"));
        res.setMedicareNumber(record.getMedicareNumber());
        res.setPayType(record.getPayType());

        Map<String, String> disability = getDisease(record.getDisability(), 9, true);
        res.setDisability(disability.get("code"));
        res.setDisabilityOther(disability.get("other"));

        res.setBloodType(record.getBloodType());
        res.setBloodrhType(record.getBloodrhType());
        res.setCulturalDegree(record.getCulturalDegree());
        res.setCulturalDegree(record.getCulturalDegree());
        res.setPositionType(record.getPositionType());
        res.setMaritalStatus(record.getMaritalStatus());

        Map<String, String> allergicHistory = getDisease(record.getAllergicHistory(), 6, true);
        res.setAllergicHistory(allergicHistory.get("code"));
        res.setAllergicHistoryOther(allergicHistory.get("other"));

        res.setWorkEnvCode(record.getWorkEnvCode());
        res.setIsPastIllness(StrUtil.isNotBlank(record.getPastIllness()) ? 1 : 2);
        res.setPastIllness(record.getPastIllness());

        res.setIsSurgery(StrUtil.isNotBlank(record.getSurgery()) ? 1 : 2);
        res.setSurgery(record.getSurgery());

        res.setIsTrauma(StrUtil.isNotBlank(record.getTrauma()) ? 1 : 2);
        res.setTrauma(record.getTrauma());

        res.setIsBloodTransfusion(StrUtil.isNotBlank(record.getBloodTransfusion()) ? 1 : 2);
        res.setBloodTransfusion(record.getBloodTransfusion());

        String gen = record.getGeneticDisorders();
        res.setIsGeneticDisorders((StrUtil.isBlank(gen) || StrUtil.equals(gen, "0")) ? 2 : 1);
        res.setGeneticDisorders(StrUtil.removePrefix(record.getGeneticDisorders(), "1#"));

        res.setKitchen(record.getKitchen());
        res.setFueltype(record.getFueltype());
        res.setWater(record.getWater());
        res.setToilet(record.getToilet());
        res.setLivestock(record.getLivestock());

        res.setPostalcode(record.getPostalcode());
        res.setPrimaryContact(record.getPrimaryContact());
        res.setPrimaryContactNumber(record.getPrimaryContactNumber());

        res.setPrimaryContact2(record.getPrimaryContact2());
        res.setPrimaryContactNumber2(record.getPrimaryContactNumber2());

        list2.add(res);
    }

    public Map<String, String> getDisease(String data, int len, boolean isinput) {
        Map<String, String> map = new HashMap<>();
        if (StrUtil.isNotBlank(data)) {
            List<String> strings = CollUtil.newArrayList(data.split(BasicConstant.JIONSTR_1));
            if (strings.contains("1")) { // 选中的是无
                map.put("code", "1");
                map.put("other", null);
                return map;
            }
            StringBuilder sb = new StringBuilder();
            String[] str = {"A", "B", "C", "D"};
            for (int a = 2; a < len; a++) {
                if (strings.contains(a + "")) {
                    String other = a + "";
                    if (a >= 10) {
                        other = str[a - 10];
                    }
                    sb.append(other).append(BasicConstant.JIONSTR_1);
                }
            }
            map.put("code", StrUtil.removeSuffix(sb.toString(), BasicConstant.JIONSTR_1));
            if (isinput && strings.contains(len - 1 + "")) {
                map.put("other", strings.get(strings.size() - 1));
            }
        } else {
            map.put("code", "1");
            map.put("other", null);
        }
        return map;
    }

}
